import { IAppThemeService, IParam } from 'ibz-core';
import { PresetTheme, ThemeOptions } from '../../config/theme-config';
/**
 * @description 应用主题服务
 * @export
 * @class AppThemeService
 * @implements {IAppThemeService}
 */
export class AppThemeService implements IAppThemeService {
  /**
   * @description 应用主题服务实例对象
   * @private
   * @static
   * @type {AppThemeService}
   * @memberof AppThemeService
   */
  private static instance: AppThemeService;

  /**
   * @description 预置主题
   * @private
   * @type {IParam[]}
   * @memberof AppThemeService
   */
  private presetTheme: IParam[] = [];

  /**
   * @description 主题配置
   * @private
   * @type {IParam[]}
   * @memberof AppThemeService
   */
  private themeOptions: IParam[] = [];

  /**
   * @description <html> dom对象
   * @private
   * @type {HTMLElement}
   * @memberof AppThemeService
   */
  private htmlElement: HTMLElement = document.documentElement;

  /**
   * Creates an instance of AppThemeService.
   * @memberof AppThemeService
   */
  constructor() {
    this.presetTheme = PresetTheme;
    this.themeOptions = ThemeOptions;
  }

  /**
   * @description 获取应用主题服务(单例模式)
   * @static
   * @return {AppThemeService}
   * @memberof AppThemeService
   */
  public static getInstance(): AppThemeService {
    if (!this.instance) {
      this.instance = new AppThemeService();
    }
    return this.instance;
  }

  /**
   * @description 初始化应用主题
   * @return {*}  {{ themeOptions: IParam[], activeTheme: { isCustom: boolean, theme: string } }}
   * @memberof AppThemeService
   */
  public initAppTheme(): { themeOptions: IParam[]; activeTheme: { isCustom: boolean; theme: string } } {
    const activeTheme = this.getActiveUITheme();
    this.htmlElement.classList.add(activeTheme.theme);
    return {
      themeOptions: this.getThemeOptions(),
      activeTheme: activeTheme,
    };
  }

  /**
   * @description 获取当前激活主题
   * @return {*}  {{ isCustom: boolean, theme: string }}
   * @memberof AppThemeService
   */
  public getActiveUITheme(): { isCustom: boolean; theme: string } {
    const active = localStorage.getItem('activeUITheme');
    if (active) {
      return JSON.parse(active);
    }
    return {
      isCustom: false,
      theme: 'default',
    };
  }

  /**
   * @description 设置当前激活主题
   * @param {string} theme 主题
   * @param {boolean} [isCustom=false] 是否自定义
   * @memberof AppThemeService
   */
  public setActiveUITheme(theme: string, isCustom: boolean = false) {
    localStorage.setItem(
      'activeUITheme',
      JSON.stringify({
        isCustom: isCustom,
        theme: theme,
      }),
    );
  }

  /**
   * @description 获取预置主题
   * @return {*}  {IParam[]}
   * @memberof AppThemeService
   */
  public getPresetTheme(): IParam[] {
    return this.presetTheme;
  }

  /**
   * @description 设置自定义配置
   * @param {IParam} item 自定义配置
   * @memberof AppThemeService
   */
  public setCustomOptions(item: IParam) {
    this.htmlElement.style.setProperty(item.key, item.default);
    if (item.shade) {
      this.htmlElement.style.setProperty(`${item.key}-shade`, item.shade);
    }
    if (item.tint) {
      this.htmlElement.style.setProperty(`${item.key}-tint`, item.tint);
    }
  }

  /**
   * @description 删除自定义配置
   * @param {IParam} item 自定义配置
   * @memberof AppThemeService
   */
  public removeCustomOptions(item: IParam) {
    this.htmlElement.style.removeProperty(item.key);
    if (item.shade) {
      this.htmlElement.style.removeProperty(`${item.key}-shade`);
    }
    if (item.tint) {
      this.htmlElement.style.removeProperty(`${item.key}-tint`);
    }
  }

  /**
   * @description 根据标识获取css变量值
   * @param {string} tag 变量标识
   * @return {*}  {string}
   * @memberof AppThemeService
   */
  public getCssVariablet(tag: string): string {
    return (getComputedStyle(this.htmlElement).getPropertyValue(tag) || '').trim();
  }

  /**
   * @description 获取主题配置
   * @return {*}  {IParam[]}
   * @memberof AppThemeService
   */
  public getThemeOptions(): IParam[] {
    const options: IParam[] = [];
    let backOptions: IParam[] = [];
    const backOptionsStr = localStorage.getItem('customUIThemeOptions');
    if (backOptionsStr) {
      backOptions = [...JSON.parse(backOptionsStr)];
    }
    this.themeOptions.forEach((group: IParam) => {
      const items: IParam[] = [];
      if (group.items && group.items.length > 0) {
        group.items.forEach((item: IParam) => {
          const key = `--ion-${group.name.toLowerCase()}-${item.name.toLowerCase()}`;
          const changeItem = backOptions.find((item: IParam) => key === item.key);
          if (changeItem) {
            this.setCustomOptions(changeItem);
          }
          if (group.name === 'color') {
            Object.assign(item, {
              key: key,
              default: changeItem ? changeItem.default : this.getCssVariablet(key),
              shade: changeItem ? changeItem.shade : this.getCssVariablet(`${key}-shade`),
              tint: changeItem ? changeItem.tint : this.getCssVariablet(`${key}-tint`),
              showChild: false,
              isChange: changeItem ? true : false,
            });
          } else {
            Object.assign(item, {
              key: key,
              default: changeItem ? changeItem.default : this.getCssVariablet(key),
              isChange: changeItem ? true : false,
            });
          }
          items.push(item);
        });
      }
      options.push({
        name: group.name,
        title: group.title,
        lanResTag: group.lanResTag,
        items: items,
      });
    });
    this.themeOptions = options;
    return options;
  }

  /**
   * @description 应用自定义主题
   * @param {string} theme 主题基调
   * @param {IParam[]} options 配置
   * @memberof AppThemeService
   */
  public applyCustomTheme(theme: string, options: IParam[]) {
    this.setActiveUITheme(theme, true);
    const changeOptions: IParam[] = this.findChangeOptions(options);
    if (changeOptions.length > 0) {
      localStorage.setItem('customUIThemeOptions', JSON.stringify(changeOptions));
    }
  }

  /**
   * @description 查找更改的自定义配置
   * @private
   * @param {IParam[]} options
   * @return {*}  {IParam[]}
   * @memberof AppThemeService
   */
  private findChangeOptions(options: IParam[]): IParam[] {
    const change: IParam[] = [];
    options.forEach((option: IParam) => {
      if (option.items && option.items.length > 0) {
        option.items.forEach((item: IParam, _index: number) => {
          if (item.isChange) {
            change.push(item);
          }
        });
      }
    });
    return change;
  }

  /**
   * @description 切换预置主题
   * @param {string} oldVal 旧主题标识
   * @param {string} newVal 新主题标识
   * @param {IParam[]} options 主题配置
   * @return {*}
   * @memberof AppThemeService
   */
  public changeInternalTheme(oldVal: string, newVal: string, options: IParam[]) {
    const element = document.documentElement;
    if (oldVal) {
      element.classList.remove(oldVal);
    }
    if (newVal) {
      element.classList.add(newVal);
    }
    this.setActiveUITheme(newVal);
    this.resetAppTheme(options);
  }

  /**
   * @description 重置主题
   * @param {*} options 主题配置
   * @memberof AppThemeService
   */
  public resetAppTheme(options: any) {
    options.forEach((option: IParam) => {
      (option.items || []).forEach((item: IParam) => {
        if (item.isChange) {
          item.isChange = false;
          this.removeCustomOptions(item);
          item.default = this.getCssVariablet(item.key);
          if (option.name == 'color') {
            item.shade = this.getCssVariablet(`${item.key}-shade`);
            item.tint = this.getCssVariablet(`${item.key}-tint`);
          }
        }
      });
    });
    this.removeLocalStorage('customUIThemeOptions');
  }

  /**
   * @description 根据key删除本地存储
   * @private
   * @param {string} key
   * @memberof AppThemeService
   */
  private removeLocalStorage(key: string) {
    localStorage.removeItem(key);
  }
}
